CON

  ' The PropScope uses a 6.25 MHz crystal and th 16x multiplier for 100 MHz
  _clkmode      = xtal1 + pll16x
  _clkfreq      = 100_000_000

  ADC_CLOCK     = 26
  PHASE_DELAY   = 3 {0 to 3}    ' Adjust to set ADC clock in phase with samples
  TX_PIN        = 30
  BAUDRATE      = 57_600

  ' Provide a delay of at least 400 clocks between starting the ADC clock and sampling
  ' Adjusted to ensure all read
  ADC_STARTUP   = (384 + 3 * 4) - 5

OBJ

  PropScope  : "PropScope.spin"


Pub Main

  PropScope.Initialize
  PropScope.High(PropScope#PWR_ENABLE)
  PropScope.High(PropScope#CHA_DC)
  waitcnt(_clkfreq + cnt)

  coginit(7, @LaunchAllCog, 0)


Dat
              org       0
LaunchAllCog  
              coginit   Cog0                    ' 0 >> 1     = 0
              coginit   Cog1                    ' 2 >> 1     = 1
              coginit   Cog2                    ' 4 >> 1     = 2
              coginit   Cog3                    ' 6 >> 1     = 3
              coginit   Cog4                    ' 1 >> 1 + 4 = 4
              coginit   Cog5                    ' 3 >> 1 + 4 = 5
              coginit   Cog6                    ' 5 >> 1 + 4 = 6
              coginit   Cog7                    ' 7 >> 1 + 4 = 7

Cog0          long      (@ReadFast + $10) << 2 | 0
Cog1          long      (@ReadFast + $10) << 2 | 1
Cog2          long      (@ReadFast + $10) << 2 | 2
Cog3          long      (@ReadFast + $10) << 2 | 3
Cog4          long      (@ReadFast + $10) << 2 | 4
Cog5          long      (@ReadFast + $10) << 2 | 5
Cog6          long      (@ReadFast + $10) << 2 | 6
Cog7          long      (@ReadFast + $10) << 2 | 7


Dat

              org       0
ReadFast
              mov       frqa, ADCClockFreq      ' Prepare ADC clock
              mov       phsa, Phase             ' Set to 0, $40_00_00_00, $80_00_00_00, or $C0_00_00_00 to select phase

              ' The number of system clocks between the cogid instruction and the wrlong instruction must be divisible by 16
              ' Adjust ADC_STARTUP to match when modifying 
              ' This is the third instruction so it fits in the hub access window
              cogid     CogIDResult             wz      ' Set Z flag if cog 0 
              ' Clock ADC only if first cog
        if_z  mov       dira, ADCClockPin       ' Set ADC clock pin as an output
        if_z  mov       ctra, ADCClockMode

              add       SetRAMAddr, CogIDResult ' Point instruction at SetPhsa to correct phsa initial value for the cog ID
              add       AddDelay, CogIDResult   ' Point instruction at AddDelay to correct delay for given cog ID
SetRAMAddr    mov       RAMAddr, Offset         ' Initialize phsa with the offset for correct value at first wrlong
              mov       Start, cnt              ' waitcnt(constant + Delays[cogid] + cnt)
AddDelay      add       Start, Delay            ' 383 min, 511 max


              ' Drive TX pin
              mov       outa, SerTXPin          ' Set serial transmit pin as an output
              mov       dira, SerTXPin          ' Set serial transmit pin high (stop condition)

              mov       Index,  PreSample       ' Index+0 = Minimum samples before trigger
              shr       Index,  #3
              min       Index,  #1

              mov       Index+1,PostSample      ' Index+1 = Samples after trigger
              shr       Index+1,#3
              min       Index+1,#1

              waitcnt   Start, #0                       
PreTrigRead
              nop
              mov       Sample, cnt
              wrlong    Sample, RAMAddr
              add       RAMAddr, #32
              nop
              nop
              djnz      Index, #PreTrigRead
              'djnz, no branch
'TODO add trigger and post-trigger sample loops
                                                
' ---------------------------------------------- Stop all other cogs -----------------------------------                                             
' TODO: Stop other cogs in an order that will ensure that there are no gaps at the end of the samples
' TODO: Determine the exact number or range of samples written after the trigger event + PostRead 
              mov       Index, #7
CogStops
              add       CogIDResult, #1
              cogstop   CogIDResult
              djnz      Index, #CogStops

              mov       TriggerTime, cnt
              sub       TriggerTime, #0         ' TODO: Subtract number of clocks after trigger
' ---------------------------------------------- DEBUG: Transmit tail of sampled data ------------------
' TODO: Change this to output all data in a binary format                                             
Display
              mov       Start, HoldOff          ' Give the user time to open a terminal
              add       Start, cnt
              waitcnt   Start,  #0

              mov       TXByte, #16             ' Clear the screen
              call      #Serout              
              mov       RAMAddr, #0
              mov       Index+1, PreSample
Transmit           
              rdlong    HexLong, RAMAddr
              and       HexLong, TenBits
              call      #TXHex

              mov       TXByte, #","
              call      #Serout

              add       RAMAddr, #4
              djnz      Index+1,#Transmit
              
              waitpeq   $, #1
              

TXHex

              mov       Index,  #3
              rol       HexLong, #4 * (8 - 3)
SendNibble
              rol       HexLong, #4
              mov       TXByte, HexLong
              and       TXByte, #$F
              cmp       TXByte, #9              wc, wz
        if_a  add       TXByte, #"A" - "9" - 1
              add       TXByte, #"0"
              call      #Serout              
              djnz      Index, #SendNibble
TXHex_ret     ret

Serout
              or        outa,   SerTXPin        'set TX_PIN high for serial transmission
              mov       BitCnt, #10             '8 bits, plus start and stop
              or        TXByte, #$1_00          'OR in a stop bit
              shl       TXByte, #1              'shift in a start bit

              mov       BitTime,Baud            'calculate the number of clock ticks for our baud rate
              add       BitTime,cnt             'add to the current system time
              
BitLoop       shr       TXByte, #1        wc    'put bit to be transmitteded into carry
              muxc      outa,   SerTXPin        'write the state of carry to the pin
              waitcnt   BitTime,Baud            'wait for the right amount of time
              djnz      BitCnt, #BitLoop        'do it again until we run out of bits to transmit
              
Serout_ret    ret




CounterMode   long      1 << 26
TriggerMask   long      $7FF
TrigerValue   long      $321
SerTXPin      long      |< TX_PIN 
Baud          long      _clkfreq / BAUDRATE
HoldOff       long      _clkfreq '/ 10
PreSample     long      128
PostSample    long      12

ADCClockPin   long      |< ADC_CLOCK
ADCClockFreq  long      $4_00_00_00
ADCClockMode  long      %00100 << 26 | ADC_CLOCK
Phase         long      $40_00_00_00 * PHASE_DELAY

A0_00         long      $A0_00
TenBits       long      %11_1111_1111
TwentyBits    long      %1111_1111_1111_1111_1111
'0,2,4,6,1,3,5,7
'Delay        long      ADC_STARTUP[8]
Delay         long      ADC_STARTUP + 80, ADC_STARTUP + 80, ADC_STARTUP + 48, ADC_STARTUP + 64, ADC_STARTUP + 32, ADC_STARTUP + 32, ADC_STARTUP + 0, ADC_STARTUP + 0
'Offset       long      0, 16, 4, 20, 8, 24, 12, 28
Offset        long      0 * 4, 4 * 4, 1 * 4, 5 * 4, 2 * 4, 6 * 4, 3 * 4, 7 * 4

Start         res       1
RAMAddr       res       1
HexLong       res       1
TXByte        res       1
BitTime       res       1
Index         res       2
BitCnt        res       1
CogIDResult   res       1
Sample        res       1
TriggerTime   res       1